<template>
  <td v-bind="cellAttributes">
    <div
      :class="{
        flex: isSelectable,
        'mr-5': isCentered && isSortable,
        'whitespace-pre-line': newlineable,
      }"
    >
      <div
        v-if="attribute === 'actions'"
        v-once
        class="absolute -left-px top-0 h-full w-px bg-neutral-200 dark:bg-neutral-700/70"
      />

      <div
        v-else-if="isPrimary"
        v-once
        style="box-shadow: 0 1px 15px rgba(0, 0, 0, 0.25)"
        class="absolute -right-px top-0 h-full w-px bg-neutral-200 dark:bg-neutral-800"
      />

      <IFormCheckbox
        v-if="isSelectable"
        :class="{ '-ml-2': !condensed }"
        :checked="isSelected"
        @click="$emit('selected', row)"
      />

      <div
        v-if="isSelectable"
        :class="{
          'left-12': !condensed,
          'left-8': condensed,
        }"
        class="absolute top-0 h-full w-px bg-neutral-200 dark:bg-neutral-800"
      />

      <component
        :is="link ? 'a' : route ? 'router-link' : 'div'"
        :class="{
          'ml-6': isSelectable && !condensed,
          'ml-2': isSelectable && condensed,
        }"
        v-bind="linkBindings"
      >
        <slot> </slot>
      </component>
    </div>
  </td>
</template>

<script setup>
import { computed } from 'vue'
import cloneDeep from 'lodash/cloneDeep'
import each from 'lodash/each'
import get from 'lodash/get'
import isObject from 'lodash/isObject'
import isString from 'lodash/isString'

import { isBlank } from '@/Core/utils'

const props = defineProps({
  row: { required: true, type: Object },
  attribute: { required: true, type: String },
  hasRequiredField: { required: true, type: Boolean },
  isPrimary: { required: true, type: Boolean },
  width: { required: true },
  minWidth: { required: true },
  link: { required: true },
  route: { required: true },
  tdClass: [String, Array, Object],
  condensed: Boolean,
  newlineable: Boolean,
  isCentered: Boolean,
  isSortable: Boolean,
  isSelected: Boolean,
  isSelectable: Boolean,
})

defineEmits(['selected'])

function replaceUrlBindings(url) {
  Object.keys(props.row).forEach(attribute => {
    url = url.replace('{' + attribute + '}', get(props.row, attribute))
  })

  return url
}

const linkBindings = computed(() => {
  if (!props.route && !props.link) {
    return {}
  }

  let bindings = { class: 'link' }

  const objectToBindings = function (object) {
    each(
      object,
      (value, key) =>
        (object[key] = isString(value) ? replaceUrlBindings(value) : value)
    )
  }

  if (props.route) {
    let to = cloneDeep(props.route)

    if (isObject(to)) {
      objectToBindings(to.params || {})
      objectToBindings(to.query || {})
    } else {
      to = replaceUrlBindings(to)
    }

    bindings.to = to
  } else {
    bindings.href = replaceUrlBindings(props.link)
  }

  return bindings
})

const cellAttributes = computed(() => ({
  style: {
    width: props.width,
    'min-width': props.minWidth,
  },
  class: [
    props.tdClass,
    'whitespace-normal group/td relative',
    props.hasRequiredField && isBlank(props.row[props.attribute])
      ? '!bg-danger-100 hover:!bg-danger-200'
      : props.isSelected
        ? '!bg-neutral-50 dark:!bg-neutral-800'
        : 'group-hover/tr:bg-neutral-50 group-hover/tr:dark:bg-neutral-800',
    {
      'text-center': props.isCentered,
      'table-primary-column': props.isPrimary === true,
      'table-actions-column': props.attribute === 'actions',
    },
  ],
}))
</script>
